<?php
// +----------------------------------------------------------------------
// | Created by Sublime: [ Cj丶Admin ]
// +----------------------------------------------------------------------
// | Copyright (c) 2021~20223[chenjia] All rights reserved.
// +----------------------------------------------------------------------
// | SiteUrl: http://www.99dn.cn
// +----------------------------------------------------------------------
// | Author: Conqweal <150672834@qq.com>
// +----------------------------------------------------------------------
// | Date: 2022/8/9 0001
// +----------------------------------------------------------------------
// | Description:人脸关键点识别系统
// +----------------------------------------------------------------------
namespace app\controller;

use app\BaseController;
use think\exception;
use think\facade\Config;
use think\facade\Db;
use think\facade\Request;
use think\facade\View;
use think\Validate;

class Index extends BaseController
{

    public function initialize()
    {

        if (Request()->action() != 'login' && !cookie('logined')) {

            header("location:" . url("index/login"));
        }
    }

    public function index()
    {

        $w                                = [];
        Request::param("item_id") && $w[] = array('a.fitem', '=', Request::param("item_id"));
        Request::param("kwd") && $w[]     = array('a.img_id', 'like', '%' . Request::param("kwd") . '%');
        if (Request::param("status") == "1") {
            $w[] = array('a.fdata', "<>", '');
        }

        if (Request::param("status") == "-1") {
            $w[] = array('a.fdata', "=", null);
        }
        $pagesize = Request::param("pagesize") ? Request::param("pagesize") : 10;
        $ls       = Db::name('imgs')->alias("a")->join('items b', 'a.fitem=b.item_id', 'left')->where($w)->field("a.fpath as  img,a.img_id as img_name,a.fdata,b.item_name,a.img_id,a.updated")->order('a.img_id', 'desc')->paginate([
            'list_rows' => $pagesize,
            'var_page'  => 'page',
            'query'     => request()->get(),
        ])->each(function ($item, $key) {
            $item['img'] = Config::get('filesystem.disks.public.url') . '/' . $item['img'];
            return $item;
        });

        $page               = $ls->render();
        $search['item_id']  = Request::param("item_id");
        $search['kwd']      = Request::param("kwd");
        $search['status']   = Request::param("status");
        $search['pagesize'] = $pagesize;
        $items              = Db::name("items")->column("item_desc,item_name", "item_id");
        $status             = [
            1  => '已标注',
            -1 => '未标注',
        ];
        $total    = $ls->total();
        $pagesize = [10, 20, 50, 100];
        return view('', compact("ls", "page", "search", "items", 'status', 'total', 'pagesize'));
    }

    public function login()
    {

        if (Request::isPost()) {
            $username = Request::post("username");
            $password = Request::post("password");
            $f        = Db::name("users")->where('username', $username)->find();
            if ($f && $f['password'] == md5($password)) {
                cookie("logined", 1);
                return redirect("index/index");
            } else {
                $this->error("登录失败，请确认密码！");
            }
        }

        return view('', ['hidemenu' => 1]);
    }

    public function fetchImgs()
    {
        try {
            $ids = Request::get("ids");
            if (!$ids) {
                throw new Exception("ids error", 1);

            }
            $ls      = Db::name('imgs')->alias("a")->join('items b', 'a.fitem=b.item_id')->where("a.img_id", "in", $ids)->field(" a.fpath as  img,b.item_desc,a.img_id as img_name,a.fdata")->limit(10)->select();
            $iconfig = [];
            foreach ($ls as $k => $v) {
                $v['img'] = Config::get('filesystem.disks.public.url') . '/' . $v['img'];
                $v['fdata'] && $iconfig += json_decode($v['fdata'], true);

                $ls[$k] = $v;

            }

            return json(['ls' => $ls, 'iconfig' => json_encode($iconfig), 'msg' => '查詢成功']);
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    public function saveImgs()
    {
        try {
            $ids = Request::post("ids");
            $ids = explode(',', $ids);
            if (!$ids) {
                throw new Exception("ids error", 1);

            }

            $ds = Request::post("ds");
            $ds = json_decode($ds, true);

            foreach ($ds as $k => $v) {
                if (!in_array($k, $ids)) {
                    continue;
                }
                if (!$v) {
                    continue;
                }
                Db::name('imgs')->where("img_id", $k)->update([
                    'fdata'   => json_encode([$k => $v]),
                    'updated' => time(),
                ]);
            }

            return json(['msg' => '保存成功']);
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    public function base64img()
    {
        $img       = Request::get("img");
        $imageInfo = getimagesize($img);
        return 'data:' . $imageInfo['mime'] . ';base64,' . chunk_split(base64_encode(file_get_contents($img)));
    }

    public function items()
    {
        $w                                  = [];
        Request::param("item_name") && $w[] = array('item_name', 'like', '%' . Request::param("kwd") . '%');

        $ls = Db::name('items')->where($w)->order('item_id', 'asc')->paginate(8);

        $page = $ls->render();

        $search['kwd'] = Request::param("kwd");
        $search['add'] = 0;

        $total = $ls->total();
        return view('', compact("ls", "page", "search", 'total'));
    }

    public function users()
    {
        $w                                 = [];
        Request::param("username") && $w[] = array('username|truename', 'like', '%' . Request::param("kwd") . '%');

        $ls = Db::name('users')->where($w)->order('id', 'asc')->paginate(8);

        $page = $ls->render();

        $search['kwd'] = Request::param("kwd");

        $total = $ls->total();
        return view('', compact("ls", "page", "search", 'total'));
    }

    public function user_edit()
    {
        try {
            if (Request::isPost()) {
                $post = Request::post();
                if (!$post['id']) {
                    unset($post['id']);
                }
                if (!$post['password']) {
                    unset($post['password']);
                } else {
                    $post['password'] = md5($post['password']);
                }
                $validate = new \app\validate\Users;

                $r = $validate->scene('saveMyProfile')->check($post);

                if (!$r) {

                    throw new Exception($validate->getError(), 1);
                } else {
                    Db::name("users")->save($post);
                    $this->success('保存成功');
                }

            } else {
                $id    = Request::get("id");
                $uinfo = Db::name("users")->find($id);
                return json(['uinfo' => $uinfo]);
            }
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    public function item_edit()
    {
        try {
            if (Request::isPost()) {
                $post = Request::post();
                if (!$post['item_id']) {
                    unset($post['item_id']);
                }

                $validate = new \app\validate\Users;

                $r = $validate->check($post);

                if (!$r) {

                    throw new Exception($validate->getError(), 1);
                } else {
                    Db::name("items")->save($post);
                    $this->success('保存成功');
                }

            } else {
                $id    = Request::get("item_id");
                $uinfo = Db::name("items")->find($id);
                return json(['item_info' => $uinfo]);
            }
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    public function logout()
    {
        cookie('logined', null);
        return redirect(url("index/login"));
    }

    public function imgdel()
    {

        try {
            $id = Request::get("id");
            if (!$id) {
                throw new Exception("id错误", 1);

            }
            Db::name("imgs")->delete($id);
            $this->success('已删除');
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    public function userdel()
    {

        try {
            $id = Request::get("id");
            if (!$id) {
                throw new Exception("id错误", 1);

            }
            Db::name("users")->delete($id);
            $this->success('已删除');
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    public function itemdel()
    {
        try {
            $item_id = Request::get("item_id");
            if (!$item_id) {
                throw new Exception("id错误", 1);

            }
            $f = Db::name("imgs")->where('fitem', $item_id)->count();
            if ($f) {
                throw new Exception("有图片绑定该项目集，无法删除", 1);
            }
            Db::name("items")->delete($item_id);
            $this->success('已删除');
        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    public function upload()
    {
        if (Request::isAjax()) {
            $files   = request()->file('myfile');
            $item_id = request()->post("item_id");

            try {
                validate(['image' => 'fileSize:102400|fileExt:jpg|image:1024,1024,jpg'])->check($files);

                $time = time();
                $data = [];

                foreach ($files as $file) {
                    $r      = \think\facade\Filesystem::disk('public')->putFile('topic', $file);
                    $r      = str_replace("\\", "/", $r);
                    $data[] = [
                        'fpath'   => $r,
                        'created' => $time,
                        'updated' => $time,
                        'fitem'   => $item_id,
                    ];
                }

                Db::name("imgs")->insertAll($data);
                $this->success('上传完成');

            } catch (Exceptoin $e) {
                $this->error($e->getMessage());
            }
        }
    }

    public function export()
    {
        try {

            $item_id = request()->get("item_id");
            if (!$item_id) {
                throw new Exception("参数错误", 1);

            }
            $req = request()->get();

            $main = Db::name("items")->where("item_id", $item_id)->find();

            $item_name = $main['item_name'];

            $base_dir   = "export/" . $item_name;
            $store_path = Config::get('filesystem.disks.public.root');
            $from_path  = $store_path . "/";

            $ls = Db::name("imgs")->where("fitem", $item_id)->select()->toArray();

            $all = [];

            $store_full_path = dirname($store_path) . $base_dir;

            $this->mkdirs($store_full_path . "/images");
            $i = 0;

            foreach ((array) $ls as $v) {
                $ext = [];
                if (!$v['fdata']) {
                    continue;
                }

                $fdata = json_decode($v['fdata'], true);

                $ext['img_name'] = "images/" . basename($v['fpath']);
                $fdata           = $this->convertImgData($fdata, $ext);

                $all[] = $fdata;

                copy($from_path . $v['fpath'], $store_full_path . "/images/" . basename($v['fpath']));
                $i++;

            }

            if ($i < 2) {
                throw new Exception("图片未标注", 1);

            }

            //csv
            $data = $this->createCsv($store_full_path, $item_name, $all, $req);
            $this->success('已导出');

        } catch (Exception $e) {
            $this->error($e->getMessage());
        }
    }

    private function convertImgData($data, $ext)
    {

        $data = array_shift($data);

        $r = [
            'img_name' => $ext['img_name'],
            'scale'    => 1,
            'center_w' => $data['size']['width'] / 2,
            'center_h' => $data['size']['height'] / 2,
        ];
        if ($data['shapes']) {

            foreach ((array) $data['shapes'][0]['featurePoints'] as $k => $v) {
                $r[$v['label'] . '_x'] = $v['x'];
                $r[$v['label'] . '_y'] = $v['y'];
                //$r['original_'.$k.'_x'] = $v['x'];
                //$r['original_'.$k.'_y'] = $v['y'];

            }
        }
        return $r;
    }

    private function createCsv($store_full_path, $item_name, $data, $req)
    {

        $head = array_keys($data[0]);
        $cfg  = [
            'train' => $req['train'],
            'test'  => $req['test'],
            'valid' => $req['valid'],
        ];

        $total  = count($data);
        $rate_t = array_sum($cfg);

        foreach ($cfg as $k => $rate) {
            $ct    = ceil($total * $rate / $rate_t);
            $r     = array_splice($data, 0, $ct);
            $fname = $store_full_path . '/face_landmarks_' . $item_name . '_' . $k . '.csv';
            $this->exportCsv($fname, $head, $r);
        }

    }

    private function exportCsv(string $file, array $head, array $exportList)
    {

        $csv = fopen($file, 'w');
        if (!$csv) {
            return false;
        }

        //文件头
        $headList = [];
        foreach ($head as $key => $value) {
            $headList[$key] = iconv('utf-8', 'gb2312', $value);
        }
        unset($key);
        unset($value);
        fputcsv($csv, $headList);

        //文件内容
        foreach ($exportList as $exportInfo) {
            foreach ($exportInfo as $key => $value) {

                $exportInfo[$key] = iconv('utf-8', 'gb2312', $value);

            }
            fputcsv($csv, $exportInfo);
        }

        fclose($csv);
        return true;
    }

/**
 * 递归生成目录
 * @param  [type] $dir [description]
 * @return [type]      [description]
 */
    public function mkdirs($dir)
    {

        if (!is_dir($dir)) {
            if (!$this->mkdirs(dirname($dir))) {
                return false;
            }
            if (!mkdir($dir, 0777)) {
                return false;
            }
        }
        return true;
    }

}
